#include "Object.h"
#include <iostream>

using namespace std;

Object::Object(void) : charTexture(NULL){
	width = 0;
	height = 0;
	numberOfImages = 1;
	hOff = Vector3D();
	spriteImageNumber = 0;
	onGround = false;
	haveTexture = false;

	r = 1.0f;
	g = 1.0f;
	b = 1.0f;
	a = 1.0f;

	speed = 1.0f;

	life = 1.0f;

	hit = false;

	counter = 0.0;

	startAnimation = false;
	animationFinished = false;
	letOffset = false;
}

Object::~Object(void){
	if(charTexture != NULL){
		delete [] charTexture;
		charTexture = NULL;
	}
}

void Object::Init(Vector3D position, float width, float height){
	this->width = width;
	this->height = height;
	this->position = position;
	this->oOff = position;

	theBox = new BoundingBox[3];
	theBox[FULLBODY].InitBox(Vector3D(position.x, position.y, 0), width, height, 1);
	theBox[LEG].InitBox(Vector3D(position.x, position.y + (height / 4) * 3, 0), width, height / 4, 1);
	theBox[HEAD].InitBox(Vector3D(position.x, position.y + (height / 4), 0), width, height / 4, 1);

	render = true;
}

void Object::SetLife(float life){
	this->life = life;
}

void Object::ReduceLife(float damageTaken){
	if(!hit){
		hit = true;
		this->life = this->life - damageTaken;

		if (damageTaken != 0 )
		{
			this->SetColor(1.0, 0.0, 0.0, 0.5);
			hitTimer.StartTimer(0, 0, 1, 0);
		}
	}
}

float Object::GetLife(void){
	return this->life;
}

void Object::SetColor(float r, float g, float b, float a){
	this->r = r;
	this->b = b;
	this->g = g;
	this->a = a;
}

void Object::InitLine(Vector3D startPos, Vector3D endPos){
	theLine.InitLine(startPos, endPos);
}

void Object::SetOnGround(bool ground){
	onGround = ground;
}

bool Object::GetOnGround(void){
	return onGround;
}

void Object::InitSprite(int AmountOfSprites){
	charTexture = new TextureImage[AmountOfSprites];
}

void Object::SetSprite(int spriteNumber, char *imageFile){
	LoadTGA(&charTexture[spriteNumber], imageFile);
	haveTexture = true;
}

void Object::SetSpriteImageNumber(int ImageNumber){
	this->spriteImageNumber = ImageNumber;
	
	if(startAnimation)
		startAnimation = false;

	if(countdownTimer.CheckIfTimerRunning()){
		countdownTimer.StopTimer();
	}
}

void Object::PlaySpriteAnimation(int FirstSprite, int LastSprite, int Interval){
	if(countdownTimer.CheckIfTimerEnd()){
		if(!startAnimation){
			this->SetSpriteImageNumber(FirstSprite);
			startAnimation = true;
			animationFinished = false;
		}else{
			if(spriteImageNumber == LastSprite){
				animationFinished = true;
				this->spriteImageNumber = FirstSprite;
			}else{
				animationFinished = false;
				this->spriteImageNumber++;
			}
		}

		countdownTimer.StartTimer(0, 0, 0, Interval);
	}
}

int Object::GetSpriteImageNumber(void){
	return spriteImageNumber;
}

void Object::RenderObject(void){
	if(render){
		glPushAttrib(GL_CURRENT_BIT);
		//theBox.DrawBox();
		//legBox.DrawBox();
		//theLine.DrawLine();
		glPushMatrix();
			glTranslatef(position.x, position.y, 0);
			glEnable(GL_TEXTURE_2D);
			glEnable(GL_BLEND);
			glColor4f(r, g, b, a);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			if(haveTexture){
				glBindTexture(GL_TEXTURE_2D, charTexture[spriteImageNumber].texID);
				glBegin(GL_QUADS);
				if(invertImage){
					glTexCoord2f(0, 1);
					glVertex2f(0, 0);

					glTexCoord2f(0, 0);
					glVertex2f(0, this->GetHeight());

					glTexCoord2f(1, 0);
					glVertex2f(this->GetWidth(), this->GetHeight());

					glTexCoord2f(1, 1);
					glVertex2f(this->GetWidth(), 0);
				}else{
					glTexCoord2f(1, 1);
					glVertex2f(0, 0);

					glTexCoord2f(1, 0);
					glVertex2f(0, this->GetHeight());

					glTexCoord2f(0, 0);
					glVertex2f(this->GetWidth(), this->GetHeight());

					glTexCoord2f(0, 1);
					glVertex2f(this->GetWidth(), 0);
				}
			}else{
				glVertex2f(0, 0);

				glVertex2f(0, this->GetHeight());

				glVertex2f(this->GetWidth(), this->GetHeight());

				glVertex2f(this->GetWidth(), 0);
			}
			glEnd();
			glDisable(GL_BLEND);
			glDisable(GL_TEXTURE_2D);
		glPopMatrix();
		glPopAttrib();
	}
}

void Object::MoveMeLeftRight(bool mode, float elapsed){
	if(mode){
		//Left
		this->invertImage = true;

		//if(this->GetOnGround())
		//	this->SetPosition(Vector3D(this->GetPosition().x - this->GetSpeed() * elapsed, this->GetPosition().y - GRAVITY, 0));
		//else
		
		if(this->GetPosition().x > 400)
			this->SetPosition(Vector3D(this->GetPosition().x + this->GetDirection().x * this->GetSpeed() * elapsed, this->GetPosition().y, 0));
		else
			this->hOff.Set(this->hOff.x + this->GetDirection().x * this->GetSpeed() * elapsed, this->hOff.y, 0);
			
			
			
	}else{
		//Right
		this->invertImage = false;

		//if(this->GetOnGround())
		//	this->SetPosition(Vector3D(this->GetPosition().x + this->GetSpeed() * elapsed, this->GetPosition().y - GRAVITY, 0));
		//else
		
		if(this->GetPosition().x < 400)
			this->SetPosition(Vector3D(this->GetPosition().x + this->GetDirection().x * this->GetSpeed() * elapsed, this->GetPosition().y, 0));
		else
			this->hOff.Set(this->hOff.x + this->GetDirection().x * this->GetSpeed() * elapsed, this->hOff.y, 0);
	}

	//this->SetDirection(this->GetDirection());
	//this->SetPosition(Vector3D(this->GetPosition().x + this->GetDirection().x * this->GetSpeed() * elapsed, this->GetPosition().y, 0));
}

void Object::WallHit(float elapsed){
	this->SetPosition(Vector3D(this->GetPosition().x + this->GetDirection().x * this->GetSpeed() * elapsed, this->GetPosition().y, 0));
}

bool Object::UpdateObject(Vector3D offset, float elapsedTime){
	/*if(invertImage)
		posX += 1 + 1 * elapsedTime;
	else
		posX -= 1 + 1 * elapsedTime;

	this->SetPosition(posX, posY);*/

	float tempX = 0;
	float tempY = 0;
	
	if(!letOffset)
	{
		tempX = offset.x - oOff.x;	
		tempY = offset.y - oOff.y;
	}
	/*else
	{
		if(offset.x > 400)
		{
			tempX = offset.x - oOff.x - 400;
			tempY = offset.y - oOff.y - 400;
		}
	}*/
	//offsetX = offset.x;
	//offsetY = offset.y;

	if(!onGround){
		
		if(letOffset)
			this->hOff.y = this->hOff.y + (GRAVITY * elapsedTime);
		else
			this->position.y = this->position.y + (GRAVITY * elapsedTime);
	}else{
		
		if(letOffset)
			this->hOff.y = this->hOff.y;
		else 
			this->position.y = this->position.y;
	}

	//position = position + direction * speed * elapsedTime;

	if(!letOffset)
	{
		position.x -= tempX;
		position.y -= tempY;
	}
	/*else
	{
		if(offset.x > 400)
		{
			position.x -= tempX;
			position.y -= tempY;
		}
	}*/

	theBox[FULLBODY].InitBox(Vector3D(position.x, position.y, 0), width, height, 1);
	theBox[LEG].InitBox(Vector3D(position.x, position.y + (height / 4) * 3, 0), width, height / 4, 1);
	theBox[HEAD].InitBox(Vector3D(position.x, position.y + (height / 4), 0), width, height / 4, 1);

	if(!letOffset)
		this->oOff = offset;
	/*else
	{
		if(offset.x > 400)
			this->oOff = offset;
	}*/

	if(hit && hitTimer.CheckIfTimerEnd()){
		hit = false;
		this->SetColor(1.0, 1.0, 1.0, 1.0);
	}

	if(hitTimer.CheckIfTimerRunning())
		hitTimer.UpdateTimer();

	if(countdownTimer.CheckIfTimerRunning())
		countdownTimer.UpdateTimer();

	return false;
}

void Object::SetDirection(Vector3D direction){
	this->direction = direction;

	/*if(direction.x < 0){
		invertImage = false;
	}else{
		invertImage = true;
	}*/
	//invertImage = invertPosition;
}

Vector3D Object::GetDirection(void){
	return direction;
}

void Object::SetSpeed(float speed){
	this->speed = speed;
}

float Object::GetSpeed(void){
	return speed;
}

BoundingBox Object::GetBoundingBox(COLLISIONTYPE boxType){
	return theBox[boxType];
}

BoundingLine Object::GetBoundingLine(void){
	return theLine;
}

void Object::SetPosition(Vector3D position){
	this->position = position;
	theBox[FULLBODY].InitBox(Vector3D(position.x, position.y, 0), width, height, 1);
	theBox[LEG].InitBox(Vector3D(position.x, position.y + (height / 4) * 3, 0), width, height / 4, 1);
	theBox[HEAD].InitBox(Vector3D(position.x, position.y + (height / 4), 0), width, height / 4, 1);
}

void Object::SetSize(float width, float height){
	this->width = width;
	this->height = height;
}

Vector3D Object::GetPosition(void){
	return position;
}

float Object::GetWidth(void){
	return width;
}

float Object::GetHeight(void){
	return height;
}